#pragma once
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cerrno>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include "Common.hpp"
#include "Log.hpp"
#include "InetAddr.hpp"
#include <signal.h>
#include"ThreadPool.hpp"
#include<functional>
#include"Protocol.hpp"
//#include"CommandExe.hpp"
using namespace LogModule;
using namespace LockModule;
using namespace ThreadPoolModule;
#define BACKLOCK 8
static const uint16_t defaultport = 8080;

using task_t =std::function<void(void)>;
using handler_t = std::function<std::string(std::string& message)>;

class TcpServer
{
  
    struct ThreadData
    {
        int _sockfd;
        TcpServer *Self;
    };

public:
    TcpServer(handler_t handler,uint16_t port = defaultport)
        : _isrunning(false), _port(port),_handler(handler)
    {}

    void InitServer()
    {
        _listensockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensockfd < 0)
        {
            LOG(LogLevel::FATAL) << "socket fail";
            Die(SOCKET_ERR);
        }
        LOG(LogLevel::INFO) << "socket success ,sockfd is " << _listensockfd;

        // bind
        struct sockaddr_in local;
        memset(&local, 0, sizeof local);
        local.sin_addr.s_addr = INADDR_ANY;
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        int n = bind(_listensockfd, CONV(&local), sizeof local);
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "Bind fail " << strerror(errno);
            Die(BIND_ERR);
        }
        LOG(LogLevel::INFO) << "Bind success";
        // tcp是需要建立链接的，tcp需要将socket设置为监听状态
        n = listen(_listensockfd, BACKLOCK);
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "Listen fail";
            Die(LISTEN_ERR);
        }
        LOG(LogLevel::INFO) << "Listen success";
        // signal(SIGCHLD,SIG_IGN);// 方法一：子进程退出，OS自动回收，不用手动wait
    }
    void HandlerRequest(int sockfd)
    {
        LOG(LogLevel::DEBUG) << "进入 HandlerRequest ";
        char buff[4096];
        std::string package;
        while (true)
        {

            // ssize_t n = read(sockfd, buff, sizeof(buff) - 1);
            ssize_t n = recv(sockfd, buff, sizeof(buff) - 1,0);
            if (n > 0)
            {
                std::cout<<"n的值为"<<n;
                buff[n] = 0;
                package += buff;

              
                LOG(LogLevel::INFO) << "Client say@" << buff;
                string result= _handler(package);
                if(result.empty())
                {
                    continue;
                }

                send(sockfd, result.c_str(), result.size(),0);
            }
            else if (n == 0)
            {
                // read返回0表示对方关闭了连接,即客户端退出
                LOG(LogLevel::INFO) << "client quit";
                break;
            }
            else
            {
                LOG(LogLevel::ERROR) << "write fail";
                break;
            }
        }
        close(sockfd); // 避免fd泄漏问题
    }
    static void *ThreadEntry(void *argc)
    {
        pthread_detach(pthread_self());//它在结束时，系统会自动回收其占用的所有资源,不用手动join
        ThreadData *data = (ThreadData *)argc;
        data->Self->HandlerRequest(data->_sockfd);
        return nullptr;
    }
    void Start()
    {
        if (_isrunning)
            return;
        _isrunning = true;
        while (_isrunning)
        {
            // 不能直接获取数据，要先等待链接
            struct sockaddr_in peer;
            socklen_t len = sizeof peer;
            int sockfd = accept(_listensockfd, CONV(&peer), &len);
            if (sockfd < 0)
            {
                LOG(LogLevel::WARING) << "accept fail " << strerror(errno);
                continue;
            }
            LOG(LogLevel::INFO) << "accept success ,sockfd is " << sockfd;

            InetAddr addr(peer);
            LOG(LogLevel::INFO) << "client info: " << addr.Addr();

            //多进程版本
            //     pid_t id=fork();
            //     if(id==0)
            //     {

            //         close(_listensockfd);
            //         if(fork()>0)//方法二孤儿进程被OS领养
            //         exit(0);
            //     HandlerRequest(sockfd);
            //     exit(0);
            // }
            // close(sockfd);
            // int rid=waitpid(id,nullptr,0);
            //     if(rid<0)
            //     LOG(LogLevel::WARING)<<"waitpid error";
            // }

            //多线程版本
            // pthread_t tid;
            // ThreadData *data = new ThreadData;
            // data->_sockfd = sockfd;
            // data->Self = this;
            // pthread_create(&tid, nullptr, ThreadEntry, (void *)data);
            
            //线程池版本,适合处理短任务，或者用户少的情况
            //task_t f=bind(&TcpServer::HandlerRequest,this,sockfd);
            //ThreadPool<task_t>::getinstance()->Equeue(f);
            //下面的写法也可以
            ThreadPool<task_t>::getinstance()->Equeue([this,sockfd](){this->HandlerRequest(sockfd);});
        }
    }
    void Stop(){
        _isrunning=0;
    }
    ~TcpServer() {}

private:
    int _listensockfd;
    uint16_t _port;
    bool _isrunning;
    handler_t  _handler;
};